use std::collections::HashMap;

#[warn(dead_code, unused_imports, unused_variables, unused_mut)]
pub struct Request{
    pub method: String,
    pub url: String,
    pub header: HashMap<String, String>,
    pub body: Vec<u8>,
}

pub struct Response{
    pub code: u32,
    pub header: HashMap<String, String>,
    pub body: Vec<u8>,
}

pub struct BasicRouter<C> where C: Fn(&Request) -> Response {
    routes: HashMap<String, C>,
}

impl<C> BasicRouter<C> where C: Fn(&Request) -> Response {
    pub fn new() -> BasicRouter<C> {
        BasicRouter {
            routes: HashMap::new(),
        }
    }

    pub fn add_route(&mut self, method: &str, url: &str, callback: C) {
        self.routes.insert(format!("{}{}",  url,method), callback);
    }

    pub fn handle_request(&self, request: &Request) -> Response {
        let callback = self.routes.get(&request.method).unwrap();
        callback(request)
    }
    
}

type BoxedCallback = Box<dyn Fn(&Request) -> Response>;

pub struct BoxedRouter {
    routes: HashMap<String, BoxedCallback>,
}

impl BoxedRouter {
    pub fn new() -> BoxedRouter {
        BoxedRouter {
            routes: HashMap::new(),
        }
    }

    // 'static 传入的函数必须有全局生命周期
    pub fn add_route<C>(&mut self, method: &str, url: &str, callback: C) where C: Fn(&Request) -> Response + 'static {
        self.routes.insert(format!("{}{}",  url,method), Box::new(callback));
    }

    pub fn handle_request(&self, request: &Request) -> Response {
        let callback = self.routes.get(&request.method).unwrap();
        callback(request)
    }
}